package cn.deschen.biz.service.impl;

import cn.deschen.biz.domain.entity.AdUnitEle;
import cn.deschen.biz.dto.unit.UnitEleDTO;
import cn.deschen.biz.mapper.AdUnitEleMapper;
import cn.deschen.biz.service.*;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

import static cn.deschen.biz.constants.UnitEleConstants.EleType.*;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author deschen
 * @since 2021-06-21
 */
@Service
public class AdUnitEleServiceImpl extends ServiceImpl<AdUnitEleMapper, AdUnitEle> implements AdUnitEleService {

    @Autowired
    private AdTagService tagService;

    @Autowired
    private AdKeywordService keywordService;

    @Autowired
    private AdRegionService regionService;

    @Autowired
    private AdCreativeService creativeService;

    @Autowired
    private AdUnitEleMapper unitEleMapper;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void saveBatch(Long unitId, Map<String, Set<UnitEleDTO>> eleMap) {
        List<AdUnitEle> unitEleList = new ArrayList<>();
        for (Map.Entry<String, Set<UnitEleDTO>> eleEntry : eleMap.entrySet()) {
            if (CollectionUtils.isEmpty(eleEntry.getValue())) {
                continue;
            }
            switch (eleEntry.getKey()) {
                case TAG:
                    List<Long> tagIdList = tagService.saveBatchTag(unitId, eleEntry.getValue());
                    assignUnitEleList(eleEntry.getKey(), unitId, tagIdList, unitEleList);
                    break;
                case KEYWORD:
                    List<Long> keywordIdList = keywordService.saveBatchKeyword(unitId, eleEntry.getValue());
                    assignUnitEleList(eleEntry.getKey(), unitId, keywordIdList, unitEleList);
                    break;
                case REGION:
                    List<Long> regionIdList = regionService.saveBatchRegion(unitId, eleEntry.getValue());
                    assignUnitEleList(eleEntry.getKey(), unitId, regionIdList, unitEleList);
                    break;
                case CREATIVE:
                    List<Long> creativeIdList = eleEntry.getValue().stream().map(UnitEleDTO::getEleId).collect(Collectors.toList());
                    assignUnitEleList(eleEntry.getKey(), unitId, creativeIdList, unitEleList);
                    break;
            }
        }
        saveBatch(unitEleList);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateBatch(Long unitId, Map<String, Set<UnitEleDTO>> eleMap) {
        Map<String, List<AdUnitEle>> oldEleMap = listUnitEle(unitId);
        for (Map.Entry<String, Set<UnitEleDTO>> newEleEntry : eleMap.entrySet()) {
            Collection<UnitEleDTO> unitEleDTOSet = newEleEntry.getValue();
            List<AdUnitEle> oldEleSet = oldEleMap.get(newEleEntry.getKey());
            if (CollectionUtils.isEmpty(oldEleSet)) {
                continue;
            }
            Iterator<UnitEleDTO> newEleItr = unitEleDTOSet.iterator();
            Iterator<AdUnitEle> oldEleItr = oldEleSet.iterator();
            while (newEleItr.hasNext()) {
                UnitEleDTO newEle = newEleItr.next();
                if (null != newEle.getEleId()) {
                    while (oldEleItr.hasNext()) {
                        Long oldEleId = oldEleItr.next().getEleId();
                        if (newEle.getEleId().equals(oldEleId)) {
                            newEleItr.remove();
                            oldEleItr.remove();
                            break;
                        }
                    }
                }
            }
        }

        // 移除旧的关联
        List<Long> removeUnitEleSet = oldEleMap.entrySet().stream().map(Map.Entry::getValue)
                .flatMap(Collection::stream).map(AdUnitEle::getId).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(removeUnitEleSet)) {
            removeByIds(removeUnitEleSet);
        }

        // 新增新的元素和关联
        saveBatch(unitId, eleMap);
    }

    private void assignUnitEleList(String eleType, Long unitId, List<Long> eleIdList, List<AdUnitEle> unitEleList) {
        eleIdList.stream().forEach(eleId -> {
            AdUnitEle unitEle = new AdUnitEle();
            unitEle.setUnitId(unitId);
            unitEle.setEleId(eleId);
            unitEle.setEleType(eleType);
            unitEleList.add(unitEle);
        });
    }

    /**
     * 根据推广单元ID获取对应元素
     * @param unitId
     * @return
     */
    private Map<String, List<AdUnitEle>> listUnitEle(Long unitId) {
        QueryWrapper<AdUnitEle> wrapper = new QueryWrapper<>();
        wrapper.lambda()
                .eq(AdUnitEle::getUnitId, unitId);
        List<AdUnitEle> unitEleList = list(wrapper);
        return unitEleList.stream().collect(Collectors.groupingBy(AdUnitEle::getEleType));
    }


    @Override
    public Map<String, List<UnitEleDTO>> getElesById(Long unitId) {
        List<UnitEleDTO> eleDTOS = unitEleMapper.getElesById(unitId);
        return eleDTOS.stream().collect(Collectors.groupingBy(UnitEleDTO::getEleType));
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void removeBatchByUnitIds(List<Long> unitIds) {
        QueryWrapper<AdUnitEle> wrapper = new QueryWrapper<>();
        wrapper.lambda()
                .in(AdUnitEle::getUnitId, unitIds);
        remove(wrapper);
    }


}
